home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / Main.bin / PipedInputStream.java < prev    next >
Text File  |  1998-09-22  |  9KB  |  287 lines

  1. /*
  2.  * @(#)PipedInputStream.java    1.19 98/07/01
  3.  *
  4.  * Copyright 1995-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  * 
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.io;
  16.  
  17. /**
  18.  * A piped input stream is the receiving end of a communications 
  19.  * pipe. Two threads can communicate by having one thread send data 
  20.  * through a piped output stream and having the other thread read the 
  21.  * data through a piped input stream.
  22.  *
  23.  * @author  James Gosling
  24.  * @version 1.19, 07/01/98
  25.  * @see     java.io.PipedOutputStream
  26.  * @since   JDK1.0
  27.  */
  28. public
  29. class PipedInputStream extends InputStream {
  30.     boolean closed = true;
  31.     boolean closedByReader = false;
  32.     boolean connected = false;
  33.  
  34.     /* REMIND: identification of the read and write sides needs to be
  35.        more sophisticated.  Either using thread groups (but what about
  36.        pipes within a thread?) or using finalization (but it may be a
  37.        long time until the next GC). */
  38.     Thread readSide;
  39.     Thread writeSide;
  40.  
  41.     /**
  42.      * @since   JDK1.1
  43.      */
  44.     protected static final int PIPE_SIZE = 1024;
  45.  
  46.     /**
  47.      * The circular buffer into which incoming data is placed.
  48.      * @since   JDK1.1
  49.      */
  50.     protected byte buffer[] = new byte[PIPE_SIZE];
  51.  
  52.     /*
  53.      * fill and empty pointers.  in<0 implies the buffer is empty, in==out
  54.      * implies the buffer is full
  55.      */
  56.  
  57.     /**
  58.      * @since   JDK1.1
  59.      */
  60.     protected int in = -1;
  61.  
  62.     /**
  63.      * @since   JDK1.1
  64.      */
  65.     protected int out = 0;
  66.  
  67.     /**
  68.      * Creates a piped input stream connected to the specified piped 
  69.      * output stream. 
  70.      *
  71.      * @param      src   the stream to connect to.
  72.      * @exception  IOException  if an I/O error occurs.
  73.      * @since      JDK1.0
  74.      */
  75.     public PipedInputStream(PipedOutputStream src) throws IOException {
  76.     connect(src);
  77.     }
  78.  
  79.     /**
  80.      * Creates a piped input stream that is not yet connected to a piped 
  81.      * output stream. It must be connected to a piped output stream, 
  82.      * either by the receiver or the sender, before being used. 
  83.      *
  84.      * @see     java.io.PipedInputStream#connect(java.io.PipedOutputStream)
  85.      * @see     java.io.PipedOutputStream#connect(java.io.PipedInputStream)
  86.      * @since   JDK1.0
  87.      */
  88.     public PipedInputStream() {
  89.     }
  90.  
  91.     /**
  92.      * Connects this piped input stream to a sender. 
  93.      *
  94.      * @param      src   The piped output stream to connect to.
  95.      * @exception  IOException  if an I/O error occurs.
  96.      * @since      JDK1.0
  97.      */
  98.     public void connect(PipedOutputStream src) throws IOException {
  99.     if (connected) {
  100.         throw new IOException("Pipe already connected");
  101.     }
  102.     src.connect(this);
  103.     connected = true;
  104.     }
  105.     
  106.     /**
  107.      * Receives a byte of data.  This method will block if no input is
  108.      * available.
  109.      * @param b the byte being received
  110.      * @exception IOException If the pipe is broken.
  111.      * @since     JDK1.1
  112.      */
  113.     protected synchronized void receive(int b) throws IOException {
  114.     writeSide = Thread.currentThread();
  115.     while (in == out) {
  116.         if ((readSide != null) && !readSide.isAlive()) {
  117.         throw new IOException("Pipe broken");
  118.         }
  119.         /* full: kick any waiting readers */
  120.         notifyAll();    
  121.         try {
  122.             wait(1000);
  123.         } catch (InterruptedException ex) {
  124.         throw new java.io.InterruptedIOException();
  125.         }
  126.     }
  127.     if (in < 0) {
  128.         in = 0;
  129.         out = 0;
  130.     }
  131.     buffer[in++] = (byte)(b & 0xFF);
  132.     if (in >= buffer.length) {
  133.         in = 0;
  134.     }
  135.     }
  136.  
  137.     /**
  138.      * Receives data into an array of bytes.  This method will
  139.      * block until some input is available. 
  140.      * @param b the buffer into which the data is received
  141.      * @param off the start offset of the data
  142.      * @param len the maximum number of bytes received
  143.      * @return the actual number of bytes received, -1 is
  144.      *          returned when the end of the stream is reached. 
  145.      * @exception IOException If an I/O error has occurred. 
  146.      */
  147.     synchronized void receive(byte b[], int off, int len)  throws IOException {
  148.     while (--len >= 0) {
  149.         receive(b[off++]);
  150.     }
  151.     }
  152.  
  153.     /**
  154.      * Notifies all waiting threads that the last byte of data has been
  155.      * received.
  156.      */
  157.     synchronized void receivedLast() {
  158.     closed = true;
  159.     notifyAll();
  160.     }
  161.  
  162.     /**
  163.      * Reads the next byte of data from this piped input stream. The 
  164.      * value byte is returned as an <code>int</code> in the range 
  165.      * <code>0</code> to <code>255</code>. If no byte is available 
  166.      * because this end of the stream has been reached, the value 
  167.      * <code>-1</code> is returned. This method blocks until input data 
  168.      * is available, the end of the stream is detected, or an exception 
  169.      * is thrown. 
  170.      *
  171.      * @return     the next byte of data, or <code>-1</code> if the end of the
  172.      *             stream is reached.
  173.      * @exception  IOException  if the pipe is broken.
  174.      * @since      JDK1.0
  175.      */
  176.     public synchronized int read()  throws IOException {
  177.     if (closedByReader) {
  178.         throw new IOException("InputStream closed");
  179.     }
  180.     int trials = 2;
  181.     while (in < 0) {
  182.         readSide = Thread.currentThread();
  183.         if (closed) { 
  184.         /* closed by writer, return EOF */
  185.         return -1;
  186.         }
  187.         if ((writeSide != null) && (!writeSide.isAlive()) && (--trials < 0)) {
  188.         throw new IOException("Pipe broken");
  189.         }
  190.             /* might be a writer waiting */
  191.         notifyAll();
  192.         try {
  193.             wait(1000);
  194.         } catch (InterruptedException ex) {
  195.         throw new java.io.InterruptedIOException();
  196.         }
  197.      }
  198.     int ret = buffer[out++] & 0xFF;
  199.     if (out >= buffer.length) {
  200.         out = 0;
  201.     }
  202.     if (in == out) {
  203.             /* now empty */
  204.         in = -1;        
  205.     }
  206.     return ret;
  207.     }
  208.  
  209.     /**
  210.      * Reads up to <code>len</code> bytes of data from this piped input 
  211.      * stream into an array of bytes. This method blocks until at least one
  212.      * byte of input is available. 
  213.      *
  214.      * @param      b     the buffer into which the data is read.
  215.      * @param      off   the start offset of the data.
  216.      * @param      len   the maximum number of bytes read.
  217.      * @return     the total number of bytes read into the buffer, or
  218.      *             <code>-1</code> if there is no more data because the end of
  219.      *             the stream has been reached.
  220.      * @exception  IOException  if an I/O error occurs.
  221.      * @since      JDK1.0
  222.      */
  223.     public synchronized int read(byte b[], int off, int len)  throws IOException {
  224.  
  225.     if (b == null) {
  226.         throw new NullPointerException();
  227.     } else if (off < 0 || len < 0 || off + len > b.length) {
  228.         throw new ArrayIndexOutOfBoundsException();
  229.     } else if (len == 0) {
  230.         return 0;
  231.     }
  232.  
  233.         /* possibly wait on the first character */
  234.     int c = read();        
  235.     if (c < 0) {
  236.         return -1;
  237.     }
  238.     b[off] = (byte) c;
  239.     int rlen = 1;
  240.     while ((in >= 0) && (--len > 0)) {
  241.         b[off + rlen] = buffer[out++];
  242.         rlen++;
  243.         if (out >= buffer.length) {
  244.         out = 0;
  245.         }
  246.         if (in == out) {
  247.                 /* now empty */
  248.         in = -1;    
  249.         }
  250.     }
  251.     return rlen;
  252.     }
  253.  
  254.     /**
  255.      * Returns the number of bytes that can be read from this input 
  256.      * stream without blocking. This method overrides the <code>available</code>
  257.      * method of the parent class.
  258.      *
  259.      * @return     the number of bytes that can be read from this input stream
  260.      *             without blocking.
  261.      * @exception  IOException  if an I/O error occurs.
  262.      * @since   JDK1.0.2
  263.      */
  264.   public synchronized int available() throws IOException {
  265.     if(in < 0)
  266.       return 0;
  267.     else if(in == out)
  268.       return buffer.length;
  269.     else if (in > out)
  270.       return in - out;
  271.     else
  272.       return in + buffer.length - out;
  273.   }
  274.     
  275.     /**
  276.      * Closes this piped input stream and releases any system resources 
  277.      * associated with the stream. 
  278.      *
  279.      * @exception  IOException  if an I/O error occurs.
  280.      * @since      JDK1.0
  281.      */
  282.     public void close()  throws IOException {
  283.     in = -1;
  284.     closedByReader = true;
  285.     }
  286. }
  287.